package com.ywh.composetest.activity

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.gestures.detectVerticalDragGestures
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.gestures.rememberTransformableState
import androidx.compose.foundation.gestures.transformable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import com.ywh.composetest.widget.SpacerVertical
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.math.roundToInt

//https://blog.csdn.net/Mr_Tony/article/details/118771707?ops_request_misc=%257B%2522request%255Fid%2522%253A%25226686ea6426377e958231389164b24c3c%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=6686ea6426377e958231389164b24c3c&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-118771707-null-null.142^v100^pc_search_result_base3&utm_term=compose%20%E6%89%8B%E5%8A%BF%E6%93%8D%E4%BD%9C&spm=1018.2226.3001.4187

/**
 * AnimatedVisibility{}
 * verticalScroll,horizontalScroll:
 * clickable{}
 * combinedClickable(onLongClick,onDoubleClick,onClick)//连续点击比如点3下，会触发一个DoubleClick,一个click,体验不太好。
 * PointerInputScope: detectTapGestures:基本的手势检测
 */
class GestureActivity : BaseComposeActivity() {
    val TAG = GestureActivity::class.java.simpleName

    @Composable
    override fun OnComposable(savedInstanceState: Bundle?) {
        val scrollState = rememberScrollState()
        Column(modifier = Modifier.verticalScroll(scrollState)) {

            HorizontalScrollCompose()

            SpacerVertical(height = 10.dp)

            ClickableCompose()

            SpacerVertical(height = 10.dp)

            CombinedClickableCompose()

            SpacerVertical(height = 10.dp)

            PointerInputCompose()

            SpacerVertical(height = 10.dp)

            //-----------------------drag------------------------
            Draggable_OffsetCompose()

            SpacerVertical(height = 10.dp)

            DetectDragGestures_OffsetCompose()

            SpacerVertical(height = 10.dp)

            DetectDragGesturesAfterLongPress_OffsetCompose()

            SpacerVertical(height = 10.dp)

            DetectHorizontalDragGestures_OffsetCompose()

            SpacerVertical(height = 10.dp)

            DetectVerticalDragGestures_OffsetCompose()

            SpacerVertical(height = 10.dp)

            //-----------------------drag end------------------------

            TransformableCompose()

            SpacerVertical(height = 10.dp)

            DetectTransformGestures_offset_scale_rotate_Compose()


            SpacerVertical(height = 500.dp)
        }
    }

    @Composable
    private fun DetectTransformGestures_offset_scale_rotate_Compose() {
        var scale by remember {
            mutableFloatStateOf(1f)
        }
        var rotate by remember {
            mutableFloatStateOf(0f)
        }
        var offset by remember {
            mutableStateOf(Offset.Zero)
        }

        Box(
            modifier = Modifier
                .size(200.dp, 40.dp)
                .rotate(rotate)
                .scale(scale)
                .offset { IntOffset(offset.x.roundToInt(), offset.y.roundToInt()) }
                .background(Color.Green)
                .pointerInput(Unit) {
                    detectTransformGestures { centroid, pan, zoom, rotation ->
                        scale *= zoom
                        rotate += rotation
                        offset += pan
                    }
                }
                .clickable {
                    Log.e(TAG, "检测用于平移、缩放和旋转的多点触控手势")
                }, contentAlignment = Alignment.Center
        ) {
            Text(text = "检测用于平移、缩放和旋转的多点触控手势")
        }
    }

    @Composable
    private fun TransformableCompose() {
        var scale by remember {
            mutableFloatStateOf(1f)
        }
        var rotation by remember {
            mutableFloatStateOf(0f)
        }
        var offset by remember {
            mutableStateOf(Offset.Zero)
        }
        val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
            scale *= zoomChange
            rotation += rotationChange
            offset += offsetChange
        }

        Box(
            modifier = Modifier
                .size(200.dp, 40.dp)
                .background(Color.Green)
                .transformable(state = state)
                .graphicsLayer(
                    scaleX = scale,
                    scaleY = scale,
                    rotationZ = rotation,
                    translationX = offset.x,
                    translationY = offset.y
                )
                .clickable {
                    Log.e(TAG, "检测用于平移、缩放和旋转的多点触控手势")
                }, contentAlignment = Alignment.Center
        ) {
            Text(text = "检测用于平移、缩放和旋转的多点触控手势")
        }
    }

    @Composable
    private fun DetectVerticalDragGestures_OffsetCompose() {
        val offsetY = remember {
            mutableFloatStateOf(0f)
        }

        Box(modifier = Modifier
            .size(200.dp, 40.dp)
            .background(Color.Green)
            .offset {
                IntOffset(0, offsetY.floatValue.roundToInt())
            }
            .pointerInput(Unit) {
                detectVerticalDragGestures(
                    onDragCancel = {
                        Log.e(TAG, "onDragCancel")
                    },
                    onDragStart = {
                        Log.e(TAG, "onDragStarted:${it}")
                    },
                    onDragEnd = {
                        Log.e(TAG, "onDragEnd")
                    }
                ) { change, dragAmount ->
                    change.consume()
                    offsetY.floatValue += dragAmount
                }
            }
            .clickable {
                Log.e(TAG, "拖拽Box")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "纵向拖拽\nDetectVerticalDragGestures + Offset")
        }
    }

    @Composable
    private fun DetectHorizontalDragGestures_OffsetCompose() {
        val offsetX3 = remember {
            mutableFloatStateOf(0f)
        }

        Box(modifier = Modifier
            .size(200.dp, 40.dp)
            .background(Color.Green)
            .offset {
                IntOffset(offsetX3.floatValue.roundToInt(), 0)
            }
            .pointerInput(Unit) {
                detectHorizontalDragGestures(
                    onDragCancel = {
                        Log.e(TAG, "onDragCancel")
                    },
                    onDragStart = {
                        Log.e(TAG, "onDragStarted:${it}")
                    },
                    onDragEnd = {
                        Log.e(TAG, "onDragEnd")
                    }
                ) { change, dragAmount ->
                    change.consume()
                    offsetX3.floatValue += dragAmount
                }
            }
            .clickable {
                Log.e(TAG, "拖拽Box")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "横向拖拽\nDetectHorizontalDragGestures + Offset()")
        }
    }

    @Composable
    private fun DetectDragGesturesAfterLongPress_OffsetCompose() {
        val offsetX3 = remember {
            mutableFloatStateOf(0f)
        }
        val offsetY3 = remember {
            mutableFloatStateOf(0f)
        }

        Box(modifier = Modifier
            .size(200.dp, 40.dp)
            .background(Color.Green)
            .offset {
                IntOffset(offsetX3.floatValue.roundToInt(), offsetY3.floatValue.roundToInt())
            }
            .pointerInput(Unit) {
                detectDragGesturesAfterLongPress(
                    onDragCancel = {
                        Log.e(TAG, "onDragCancel")
                    },
                    onDragStart = {
                        Log.e(TAG, "onDragStarted:${it}")
                    },
                    onDragEnd = {
                        Log.e(TAG, "onDragEnd")
                    }
                ) { change, dragAmount ->
                    change.consume()
                    offsetX3.floatValue += dragAmount.x
                    offsetY3.floatValue += dragAmount.y
                }
            }
            .clickable {
                Log.e(TAG, "拖拽Box")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "横向+纵向拖拽\ndetectDragGesturesAfterLongPress()+Offset()")
        }
    }

    @Composable
    private fun DetectDragGestures_OffsetCompose() {
        val offsetX3 = remember {
            mutableFloatStateOf(0f)
        }
        val offsetY3 = remember {
            mutableFloatStateOf(0f)
        }

        Box(modifier = Modifier
            .size(200.dp, 40.dp)
            .background(Color.Green)
            .offset {
                IntOffset(offsetX3.floatValue.roundToInt(), offsetY3.floatValue.roundToInt())
            }
            .pointerInput(Unit) {
                detectDragGestures(
                    onDragCancel = {
                        Log.e(TAG, "onDragCancel")
                    },
                    onDragStart = {
                        Log.e(TAG, "onDragStarted:${it}")
                    },
                    onDragEnd = {
                        Log.e(TAG, "onDragEnd")
                    }
                ) { change, dragAmount ->
                    change.consume()
                    offsetX3.floatValue += dragAmount.x
                    offsetY3.floatValue += dragAmount.y
                }
            }
            .clickable {
                Log.e(TAG, "拖拽Box")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "横向+纵向拖拽\nDetectDragGestures()+Offset()\n是否与最外层verticalScroll冲突")
        }
    }

    @Composable
    private fun Draggable_OffsetCompose() {
        val offsetX = remember {
            mutableFloatStateOf(0f)
        }

        Box(modifier = Modifier
            .size(200.dp, 40.dp)
            .background(Color.Green)
            .offset {
                IntOffset(offsetX.floatValue.roundToInt(), 0)
            }
            .draggable(
                orientation = Orientation.Horizontal,
                state = rememberDraggableState { delta ->
                    offsetX.floatValue += delta
                },
                onDragStarted = {
                    Log.e(TAG, "onDragStarted:${it}")
                },
                onDragStopped = {
                    Log.e(TAG, "onDragStopped:${it}")
                }
            )
            .clickable {
                Log.e(TAG, "横向拖拽的box")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "横向拖拽\noffset{}+draggable()")
        }
    }

    @Composable
    private fun PointerInputCompose() {
        Box(
            modifier = Modifier
                .height(40.dp)
                .background(Color.Green)
                .padding(horizontal = 12.dp)
                .pointerInput(Unit) {
                    detectTapGestures(
                        onPress = {
                            Log.e(TAG, "detectTapGestures:onPress:${it}")
                        },
                        onDoubleTap = {
                            Log.e(TAG, "detectTapGestures:onDoubleTap:${it}")
                        },
                        onLongPress = {
                            Log.e(TAG, "detectTapGestures:onLongPress:${it}")
                        },
                        onTap = {
                            Log.e(TAG, "detectTapGestures:onTap:${it}")
                        }
                    )

                    detectTransformGestures { centroid, pan, zoom, rotation ->

                    }
                    detectDragGesturesAfterLongPress { change, dragAmount ->

                    }


                }, contentAlignment = Alignment.Center
        ) {
            Text(text = "detectTapGestures(手势基本监听)")
        }
    }

    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    private fun CombinedClickableCompose() {
        Box(modifier = Modifier
            .height(40.dp)
            .background(Color.Green)
            .padding(horizontal = 12.dp)
            .combinedClickable(onLongClick = {
                Log.e(TAG, "onLongClick")
            }, onDoubleClick = {
                Log.e(TAG, "onDoubleClick")
            }) {
                Log.e(TAG, "clickable")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "combinedClickable(onLongClick,onDoubleClick,onClick)")
        }
    }

    @Composable
    private fun ClickableCompose() {
        Box(
            modifier = Modifier
                .height(40.dp)
                .background(Color.Green)
                .padding(horizontal = 12.dp)
                .clickable {
                    Log.e(TAG, "clickable")
                }, contentAlignment = Alignment.Center
        ) {
            Text(text = "clickable")
        }
    }

    @Composable
    private fun HorizontalScrollCompose() {
        val horizontalScrollState = rememberScrollState()
        Row(modifier = Modifier.horizontalScroll(horizontalScrollState)) {
            Box(
                modifier = Modifier
                    .size(200.dp, 50.dp)
                    .background(Color.Green)
                    .padding(horizontal = 12.dp)
                    .clickable {
                        Log.e(
                            TAG,
                            "clickable:${horizontalScrollState.maxValue}"
                        )
                        lifecycleScope.launch(Dispatchers.Main) {
                            horizontalScrollState.scrollTo(horizontalScrollState.maxValue)
                        }
                    }, contentAlignment = Alignment.Center
            ) {
                Text(text = "点我侧滑")
            }
            Box(
                modifier = Modifier
                    .size(150.dp, 50.dp)
                    .background(Color.Yellow)
                    .padding(horizontal = 12.dp)
                    .clickable {
                        Log.e(TAG, "clickable")
                    }, contentAlignment = Alignment.Center
            ) {
                Text(text = "horizontalScroll2")
            }
            Box(
                modifier = Modifier
                    .size(200.dp, 50.dp)
                    .background(Color.Green)
                    .padding(horizontal = 12.dp)
                    .clickable {
                        Log.e(TAG, "clickable")
                    }, contentAlignment = Alignment.Center
            ) {
                Text(text = "horizontalScroll3")
            }
        }
    }

}